#include <iostream>

#include <gl\glew.h>
#include <gl\freeglut.h>

#include "..\CustomMouseClass\CustomMouseClass.h"
#include "..\CameraGL\CameraGL.h"

#pragma comment (lib, "glew32.lib")
#pragma comment (lib, "freeglut.lib")

using namespace std;

MouseClass glob_UserMouse;
CameraGL glob_UserCamera;

bool glob_KeyStates[256];

double glob_AngleOfView_degs = 45,
	glob_NearPlaneDist = 1.0,
	glob_FarPlaneDist = 10000.0;


void HandleMouse ()
{
	/*VectorMath::Vector3 currMousePos = glob_UserMouse.GetCurrentPosition();
	cout << "X: " << currMousePos.GetX() << " Y: " << currMousePos.GetY() << " ";*/
	if (glob_UserMouse.IsLeftButtonDown())
	{
		glob_UserCamera.MoveForward(0.01);
	}
	if (glob_UserMouse.IsRightButtonDown())
	{
		cout << "Right button down ";
	}
	cout<<endl;

	double mouseDeltaX = glob_UserMouse.GetCurrentPosition().GetX() - glob_UserMouse.GetLastPosition().GetX();
	double mouseDeltaY = -(glob_UserMouse.GetCurrentPosition().GetY() - glob_UserMouse.GetLastPosition().GetY());
	//mouseDeltaX /= 3;
	if(mouseDeltaX > 0)
	{
		glob_UserCamera.LookRight (mouseDeltaX);
	}
	else
	{
		glob_UserCamera.LookLeft (-mouseDeltaX);
	}

	if(mouseDeltaY > 0)
	{
		glob_UserCamera.LookUp (mouseDeltaY);
	}
	else
	{
		glob_UserCamera.LookDown (-mouseDeltaY);
	}

	//glutWarpPointer (500, 500);
}

void ApplyCamera()
{
	glob_UserCamera.ApplyLook();
	//gluLookAt (30, 30, 30,
		//0, 0, 0,
		//0, 1, 0);
}

void DrawObjects()
{
	glPushMatrix();
	glColor4f(1.0, 1.0, 1.0, 1.0);
	glutSolidSphere(1, 10, 10);
	glPopMatrix();
	//0, 0, 0
	glPushMatrix();
	glTranslatef(20, 0, 0); // 0 + 10, 0 + 10, 0 + 10
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glutSolidTeapot(5);
	glPopMatrix(); //0, 0, 0
}

void Display()
{
	glClearColor (0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	//camera
	ApplyCamera();
	//------

	DrawObjects();

	glutSwapBuffers();
}


void MainLoop()
{
	Display();
	HandleMouse();
	glob_UserMouse.OverrideLastPosition (glob_UserMouse.GetCurrentPosition());
}

void HandleKeyDown (unsigned char key, int cursorX, int cursorY)
{
	glob_KeyStates[key] = true;
}

void HandleKeyUp (unsigned char key, int cursorX, int cursorY)
{
	glob_KeyStates[key] = false;
}

void ReshapeWindow(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity();

	double aspectRatio = ((float)width) / ((float)height);

	gluPerspective(glob_AngleOfView_degs, aspectRatio, glob_NearPlaneDist, glob_FarPlaneDist);
	glMatrixMode (GL_MODELVIEW);
}

void HandleMouseButtons (int button, int state, int x, int y)
{
	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		glob_UserMouse.PressLeftButton();
	}
	if(button == GLUT_LEFT_BUTTON && state == GLUT_UP)
	{
		glob_UserMouse.ReleaseLeftButton();
	}

	if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
	{
		glob_UserMouse.PressRightButton();
	}
	if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
	{
		glob_UserMouse.ReleaseRightButton();
	}
}	

void HandlePassiveMovement (int x, int y)
{
	glob_UserMouse.SetCurrentPosition ( VectorMath::Vector3(x, y));
}

void HandleActiveMovement (int x, int y)
{
	glob_UserMouse.SetCurrentPosition ( VectorMath::Vector3(x, y));
}

void InitializeWindow()
{
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
	glutInitWindowPosition (0, 0);
	glutInitWindowSize (800, 800);
	glutCreateWindow ("Camera Class Tester");
}

void RegisterCallbacks()
{
	glutDisplayFunc (Display);
	glutIdleFunc (MainLoop);
	glutKeyboardFunc (HandleKeyDown);
	glutKeyboardUpFunc (HandleKeyUp);
	glutMouseFunc (HandleMouseButtons);
	glutPassiveMotionFunc (HandlePassiveMovement);
	glutMotionFunc (HandleActiveMovement);
	glutReshapeFunc (ReshapeWindow);
}

void InitializeGL()
{
	glEnable (GL_DEPTH);
	glEnable (GL_DEPTH_TEST);
	glEnable (GL_COLOR_MATERIAL);
	glEnable (GL_LIGHTING);
	glEnable (GL_LIGHT0);
}

void InitializeWorld()
{
	glob_UserCamera.SetPosition (VectorMath::Vector3 (30, 0, 30));
}

int main(int argc, char ** argv)
{
	glutInit(&argc, argv);
	InitializeWindow();
	RegisterCallbacks();

	InitializeGL();
	InitializeWorld();

	glutMainLoop();

	return 0;
}